package com.loadburn.heron.utils;

import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.loadburn.heron.cache.WebCache;
import com.loadburn.heron.exceptions.HtmlParserException;
import com.loadburn.heron.template.Template;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author slacrey (scstlinfeng@yahoo.com)
 *         Date: 13-12-4
 */
public class HtmlParserUtils implements Serializable {

    private static final long serialVersionUID = -4270456085546124350L;
    //<!-- decorator:head -->
    private static final String HERON_HEADER_PATTERN_PLACEHOLDER = "<!--[\\s\\t\\r\\n]*?decorator" +
            "[\\s\\t\\r\\n]*?:[\\s\\t\\r\\n]*?head[\\s\\t\\r\\n]*?-->";
    //<!-- decorator:body -->
    private static final String HERON_BODY_PATTERN_PLACEHOLDER = "<!--[\\s\\t\\r\\n]*?decorator" +
            "[\\s\\t\\r\\n]*?:[\\s\\t\\r\\n]*?body[\\s\\t\\r\\n]*?-->";
    //<!-- decorator:include src="" -->
    private static final String HERON_INCLUDE_PATTERN_PLACEHOLDER = "<!--[\\s\\t\\r\\n]*?decorator" +
            "[\\s\\t\\r\\n]*?:[\\s\\t\\r\\n]*?include[\\s\\t\\r\\n]*?-->";
    //<!-- decorator:include src="" -->
    private static final String HERON_INCLUDE_FILE_PATTERN_PLACEHOLDER = "<!--[\\s\\t\\r\\n]*?decorator" +
            "[\\s\\t\\r\\n]*?:[\\s\\t\\r\\n]*?include[\\s\\t\\r\\n]*?src[\\s\\t\\r\\n]*?=[\\s\\t\\r\\n]*?\"([\\s\\S]*)\"[\\s\\t\\r\\n]*?-->";

    private static final String ATTR_BODY = "body";
    private static final String ATTR_HEAD = "head";
    private static final String ATTR_INCLUDE = "include";
    private static final String ATTR_INCLUDE_FILE = "include_file";
    private static final String _$ = "\\$";
    private static final String _REPLACE_$ = "\\\\\\$";

    private static final HashMap<String, Pattern> patternHashMap = Maps.newHashMap();

    @Inject
    private static Provider<WebCache> templateCacheProvider;

    private Document document;

    static {
        patternHashMap.put(ATTR_HEAD, Pattern.compile(HERON_HEADER_PATTERN_PLACEHOLDER, Pattern.CASE_INSENSITIVE));
        patternHashMap.put(ATTR_BODY, Pattern.compile(HERON_BODY_PATTERN_PLACEHOLDER, Pattern.CASE_INSENSITIVE));
        patternHashMap.put(ATTR_INCLUDE, Pattern.compile(HERON_INCLUDE_PATTERN_PLACEHOLDER, Pattern.CASE_INSENSITIVE));
    }

    public HtmlParserUtils(String html) {
        document = Jsoup.parse(html);
    }

    public String title() {
        if (document == null) {
            throwException("Document对象为空");
        }
        return document.title();
    }

    public void title(String text) {
        if (document == null) {
            throwException("Document对象为空");
        }
        document.title(text);
    }

    private void throwException(String message) {
        throw new HtmlParserException(message);
    }

    public String head() {
        return document.head().html();
    }

    public String body() {
        return document.body().html();
    }

    public String html() {
        return document.html();
    }

    //===========================================================

    public static String replaceBody(String html, String replace) {
        Pattern pattern = patternHashMap.get(ATTR_BODY);
        Matcher match = pattern.matcher(html);
        return match.replaceFirst(replace.replaceAll(_$, _REPLACE_$));
    }

    public static String replaceHead(String html, String replace) {
        Pattern pattern = patternHashMap.get(ATTR_HEAD);
        Matcher match = pattern.matcher(html);
        return match.replaceFirst(replace.replaceAll(_$, _REPLACE_$));
    }

    public static String includeDeclared(String html) {

        Pattern patternFile = patternHashMap.get(ATTR_INCLUDE_FILE);

        Matcher matcherFile = patternFile.matcher(html);
        String tmpFileName = null;
        while(matcherFile.find()) {
            tmpFileName = matcherFile.group(1);
            tmpFileName = FilenameUtils.separatorsToUnix(tmpFileName);
        }

        String text = null;
        if (!StringUtils.empty(tmpFileName)) {
            Map<String, Template> templateMap = (Map<String, Template>) templateCacheProvider.get().get(Template.WEB_TEMPLATE);
            if (templateMap != null) {
                Template template = templateMap.get(tmpFileName);
                if (template != null) {
                    text = template.getText();
                }
            }
        }

        if (!StringUtils.empty(text)) {
            Pattern pattern = patternHashMap.get(ATTR_INCLUDE);
            Matcher match = pattern.matcher(html);
            return match.replaceFirst(text.replaceAll(_$, _REPLACE_$));
        }
        return html;

    }

    public static void main(String[] args) {
        HtmlParserUtils.includeDeclared("<html>\n" +
                "    <head>\n" +
                "        <!-- decorator:head -->\n" +
                "    </head>\n" +
                "\t<body>\n" +
                "\t\t<div>${hello}</div>\n" +
                "\t\t<br/>\n" +
                "\t\t<div>${world}</div>\n" +
                "\t\t<br/>\n" +
                "        <!-- decorator:body -->\n" +
                "        <!-- decorator:include src=\"/template/disclaimer.html\" -->\n" +
                "\t</body>\n" +
                "</html>");
    }

}
